package config

import (
	"encoding/json"
	"gopkg.in/ini.v1"
	"logagent/taillog"
	"logagent/utils"
	"logagent/zookeeper"
	"os"
)

type AppConf struct {
	ZkConf `ini:"zk"`
}

type ZkConf struct {
	Hosts []string `ini:"hosts"`
	Path  string   `ini:"path"`
}

type RedisConf struct {
	Hosts      string `json:"hosts"`
	DB         int    `json:"db"`
	Pwd        string `json:"pwd"`
	DefaultKey string `json:"defaultkey"`
}

type Config struct {
	ChanSize int                    `json:"chan_size"`
	SinceDb  string                 `json:"since_db"`
	Collect  []*taillog.CollectConf `json:"collect"`
	RdsConf  *RedisConf             `json:"redis"`
}

var (
	Cfg        = new(Config)
	AppCfg     = new(AppConf)
	CfgVersion int32
)

func Init() {
	// 1. 读取配置文件 获取基本的配置信息
	dir, err := os.Getwd()
	if err != nil {
		utils.Fatalf("读取当前目录错误: %v", err)
	}
	path := dir + string(os.PathSeparator) + ".env"
	// 如果文件不存在则存环境变量中读取
	if _, e := os.Stat(path); e != nil && os.IsNotExist(e) {
		 utils.Fatalf("配置文件不存在")
	}
	err = ini.MapTo(AppCfg, path)
	if err != nil {
		utils.Fatalf("解析配置文件错误: %v", err)
	}
	// 2. 初始化zookeeper
	bytes := initZookeeper()
	// 3. 解析指定的值
	err = parseConf(bytes, Cfg)
	if err != nil {
		utils.Fatalf("解析配置错误: %v", err)
	}

}

func initZookeeper() []byte {
	// 1. 初始化zookeeper
	zkmgr := zookeeper.NewZookeeper(AppCfg.ZkConf.Hosts)
	// 2. 获取指定znode的值
	config, stat, err := zkmgr.Get(AppCfg.Path)
	if err != nil {
		utils.Fatalf("读取zookeeper失败: %v", err)
	}
	CfgVersion = stat.Version
	data := zkmgr.Listen(AppCfg.Path)
	go func() {
		for dt := range data {
			if dt.Version > CfgVersion && len(dt.Data) > 0 {
				conf := new(Config)
				e := parseConf(dt.Data, conf)
				if e != nil {
					utils.Printf("监听时解析文件错误, 版本号: %d", dt.Version)
					continue
				}
				utils.Printf("监听配置发生了变化, data: %s, version: %d", string(dt.Data), dt.Version)
				//taillog.update(conf.Collect)
			}
		}
	}()
	return config
}

func parseConf(bytes []byte, config *Config) error {
	e := json.Unmarshal(bytes, config)
	if e != nil {
		return e
	}
	if Cfg.ChanSize <= 0 {
		Cfg.ChanSize = 10
	}
	if Cfg.RdsConf.DefaultKey == "" {
		Cfg.RdsConf.DefaultKey = "logstash"
	}
	length := len(Cfg.Collect)
	uniqeCollect := make([]*taillog.CollectConf, 0)
	for i := 0; i < length; i++ {
		filename := Cfg.Collect[i].Filename
		j := i + 1
		for ; j < length; j++ {
			if Cfg.Collect[j].Filename == filename {
				break
			}
		}
		if j == length {
			if Cfg.Collect[i].Key == "" {
				Cfg.Collect[i].Key = Cfg.RdsConf.DefaultKey
			}
			uniqeCollect = append(uniqeCollect, Cfg.Collect[i])
		}
	}
	Cfg.Collect = uniqeCollect
	return nil
}
